package com.gateway.video.start;

import com.gateway.video.container.ModuleImpl;
import com.google.common.util.concurrent.AbstractService;
import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;

import javax.annotation.PreDestroy;
import java.util.Objects;

@Slf4j
@SpringBootConfiguration
public class Start extends AbstractService {
    @Autowired
    private ConfigurableApplicationContext applicationContext;

    @Bean
    public ModuleImpl moduleManager() {
        return new ModuleImpl();
    }

    public static void main(String[] args) {
        var applicationContext = (AnnotationConfigApplicationContext) SpringApplication.run(Start.class, args);

        var launcher = applicationContext.getBean(Start.class);
        launcher.addListener(new Listener() {
            @Override
            public void running() {
                if (log.isInfoEnabled()) {
                    log.info("Gateway started.");
                }
            }

            @Override
            public void failed(State from, Throwable failure) {
                if (log.isErrorEnabled()) {
                    if (Objects.equals(from, State.STARTING)) {
                        log.error("Unexpected error occur at gateway(failed={}) starting.", failure);
                    } else if (Objects.equals(from, State.STOPPING)) {
                        log.error("Unexpected error occur at gateway(failed={}) stopping", failure);
                    }
                }

                Runtime.getRuntime().exit(-1);
            }
        }, MoreExecutors.directExecutor());
        launcher.startAsync();

        launcher.awaitTerminated();
    }

    @Override
    protected void doStart() {
        var moduleManager = applicationContext.getBean(ModuleImpl.class);

        try {
            moduleManager.loadAll();
        } catch (Throwable ex) {
            throw new RuntimeException(ex);
        }

        notifyStarted();
    }

    @Override
    protected void doStop() {
        notifyStopped();
    }

    @PreDestroy
    public void destory() {

    }
}
